
#include "lib_music.h"
//****************************************************************

#if 1
#define  CONFIG_MUSIC_PATH  "/home/music/"
#elif 0

#endif
//****************************************************************

static  pthread_t     lib_music_thread;
static  int           lib_music_index = 1;

static  file_list_t*  lib_music_list  = NULL;

static  music_para_t  lib_music_para;

static  int           lib_music_ready = 0;

//****************************************************************

int lib_music_is_ready(void)
{
	return lib_music_ready;
}

int lib_muisc_open_stream(const char* filename)
{
	AVFormatContext* pFormatCtx;
	int				i, audioStream;
	AVCodecContext* pCodecCtx;
	AVCodec* pCodec;
	AVPacket* packet;
	uint8_t* out_buffer;
	AVFrame* pFrame;

	int ret;
	uint32_t len = 0;
	int got_picture;
	int index = 0;
	int64_t in_channel_layout;
	struct SwrContext* au_convert_ctx;
    AVDictionary * opts = NULL;
	
	char error_msg[256] ={0};

	char url[] = "/home/music/yuan.mp3";

	avdevice_register_all();
	avformat_network_init();
	
	pFormatCtx = avformat_alloc_context();

	if (avformat_open_input(&pFormatCtx, url, NULL, NULL) != 0) {
		log_e("Couldn't open input stream.\n");
		return -1;
	}
	
	if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
		log_e("Couldn't find stream information.\n");
		return -1;
	}

	av_dump_format(pFormatCtx, 0, url, 0);

	audioStream = -1;
	for (i = 0; i < pFormatCtx->nb_streams; i++)
	{
		log_d("codec_type=%d\n",pFormatCtx->streams[i]->codecpar->codec_type);
		
		if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) 
		{
			audioStream = i;
		}
	}

	if (audioStream == -1) {
		log_e("Didn't find a audio stream.\n");
		return -1;
	}

	
	pCodecCtx = avcodec_alloc_context3(NULL);
	if (!pCodecCtx){
		log_e("avcodec alloc error\n");
		return -1;
	}
	
	pCodecCtx->thread_count = 16;
			
	ret = avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[audioStream]->codecpar);
	if (ret < 0){
		log_e("avcodec parameters error\n");
		return -1;
	}
		
	pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
	if(!pCodec){
		log_e("no audio codec.\n");
		return -1;
	}
			
	log_i("audio codec name =%s\n",pCodec->name);
	

	ret = avcodec_open2(pCodecCtx, pCodec, NULL);
	if(ret < 0){
		log_e("audio codec open error.\n");
		return -1;
	}
			
	log_i("frame_size =%d\n",pCodecCtx->frame_size);
	log_i("channels   =%d\n",pCodecCtx->channels);
	log_i("sample_fmt =%d\n",pCodecCtx->sample_fmt);
	log_i("sample_rate=%d\n",pCodecCtx->sample_rate);
	
	log_i("\n");

	packet = (AVPacket*)av_malloc(sizeof(AVPacket));
	av_init_packet(packet);
	log_i("\n");

	//Out Audio Param
	uint64_t out_channel_layout = AV_CH_LAYOUT_STEREO;
	//nb_samples: AAC-1024 MP3-1152
	int out_nb_samples = pCodecCtx->frame_size;
	int out_sample_fmt = AV_SAMPLE_FMT_S16;
	int out_sample_rate = 44100;
	int out_channels = av_get_channel_layout_nb_channels(out_channel_layout);
	//Out Buffer Size

	log_i("out_channels=%d\n",out_channels);

	int out_buffer_size = av_samples_get_buffer_size(NULL, out_channels, out_nb_samples, out_sample_fmt, 1);

	log_i("out_buffer_size=%d\n",out_buffer_size);



	out_buffer = (uint8_t*)av_malloc(MAX_AUDIO_FRAME_SIZE * 2);
	pFrame = av_frame_alloc();
	
	log_i("\n");

	//FIX:Some Codec's Context Information is missing
	in_channel_layout = av_get_default_channel_layout(pCodecCtx->channels);
	log_i("in_channel_layout=%d\n",in_channel_layout);

	int sample_fmt  = 0;

	if(pCodecCtx->sample_fmt == 8)
	{
		sample_fmt = AV_SAMPLE_FMT_U8;
	}
	
	if(pCodecCtx->sample_fmt == 16)
	{
		sample_fmt = AV_SAMPLE_FMT_S16;
	}

	if(pCodecCtx->sample_fmt == 32)
	{
		sample_fmt = AV_SAMPLE_FMT_S32;
	}


	au_convert_ctx	   = swr_alloc();
	if(au_convert_ctx){
		au_convert_ctx = swr_alloc_set_opts(au_convert_ctx, 
											AV_CH_LAYOUT_STEREO, 
											AV_SAMPLE_FMT_S16, 
											pCodecCtx->sample_rate,
											in_channel_layout, 
											sample_fmt, 
											pCodecCtx->sample_rate, 0, NULL);
		swr_init(au_convert_ctx);
	}

	

	AVFrame* 		   audio_frame	   = NULL;

	audio_frame = av_frame_alloc();
	if(!audio_frame){
		log_e("pcm data buff malloc error.\n");
	}
	log_i("\n");

	while(av_read_frame(pFormatCtx, packet) >= 0)
	{
		if (packet->stream_index == audioStream) 
		{
			log_n("\n");
			ret = avcodec_send_packet(pCodecCtx, packet);
			
			log_n("\n");
			
			if (ret < 0){
				memset(error_msg,0,sizeof(error_msg));
				sprintf(error_msg, "error:%s\n", av_err2str(ret));
				log_e("%s\n",error_msg);
				return -1;
			}
			
			ret = 0;
			while(ret == 0)
			{
				log_n("\n");
				ret = avcodec_receive_frame(pCodecCtx, audio_frame);
				log_n("ret=%d\n",ret);
				if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
				{
					memset(error_msg,0,sizeof(error_msg));
					sprintf(error_msg, "error:%s\n", av_err2str(ret));
					log_e("%s\n",error_msg);
				
					break;
				}
				else if (ret < 0)
				{
					memset(error_msg,0,sizeof(error_msg));
					sprintf(error_msg, "error:%s\n", av_err2str(ret));
					log_e("%s\n",error_msg);
			
					break;
				}
				else
				{
					log_n("\n");
					if(au_convert_ctx&&out_buffer){
						log_n("\n");
						ret = swr_convert(au_convert_ctx, &out_buffer, MAX_AUDIO_FRAME_SIZE, &audio_frame->data, audio_frame->nb_samples);
						log_n("\n");
					}
				
					if(ret < 0){
						memset(error_msg,0,sizeof(error_msg));
						sprintf(error_msg, "error:%s\n", av_err2str(ret));
						log_e("%s\n",error_msg);
					}else{
						log_n("out_buffer_size=%d\n",out_buffer_size);
						queue_audio_pcm_write(out_buffer,out_buffer_size,audio_frame->pts);						
						log_n("\n");

						lib_music_ready = 1;
					}
				}
			}
			
			av_packet_unref(packet);

		}
	}

	swr_free(&au_convert_ctx);

	if(audio_frame){
		av_frame_free(&audio_frame);
		audio_frame = NULL;
	}


	av_free(out_buffer);
	avcodec_close(pCodecCtx);
	avformat_close_input(&pFormatCtx);

	return 0;
}


int lib_music_play(int type)
{
	int ret = -1;

	char filename[1024] = {0};

	//****************************************************************
	
	memset(filename,0,sizeof(filename));
	//****************************************************************
#if 1
	if(file_list_get_filenum(lib_music_list) < 2){
		return -1;
	}

	srand(lib_music_index);
	lib_music_index = rand()%file_list_get_filenum(lib_music_list);
	
	ret = file_list_get_filename(lib_music_list,filename,lib_music_index);
#endif
	//****************************************************************
	if(ret != 0){
		return -1;
	}
	//****************************************************************
	log_i("i:t:n=%d:%d:%s\n",lib_music_index,file_list_get_filenum(lib_music_list),filename);
	//****************************************************************

	return 0;
}


//****************************************************************
void* lib_music_play_task(void *arg)
{
	int ret = -1;
	struct timeval timer;	

	while(1)
	{
		//****************************************************************
		usleep(1000);

		//****************************************************************

		//ret = lib_music_play(0);
		if(ret != 0){
			continue;
		}
		//****************************************************************
		timer.tv_sec  = 6;
		timer.tv_usec = 0;
		
		switch(select(0, NULL, NULL, NULL, &timer)) 
		{
		case -1:  
			log_e("Error!\n");
			break;
		case 0: 
			break;
		default:break;
		}
		
		//****************************************************************

		

		//****************************************************************
	}
}

//****************************************************************

int lib_music_init(void)
{
	int ret  = 0;
	
	log_i("lib image init.\n");

	lib_muisc_open_stream("00");
	
	file_list_create(&lib_music_list,CONFIG_MUSIC_PATH,MEDIA_TYPE_MUSIC,"./musicfile.list");
	if(!lib_music_list){
		log_e("image list error\n");
		return -1;
	}
	
	ret=pthread_create(&lib_music_thread, NULL, lib_music_play_task, NULL);
	if(ret != 0){
		log_e("thread error=%s\n",strerror(ret));
		return -1;
	}



	return 0;
}


int lib_music_deinit(void)
{

	



	return 0;
}

//****************************************************************

